package com.swak.entity;

import java.io.Serializable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.function.Function;

import com.swak.annotation.ApiDoc;
import com.swak.exception.ErrorCode;
import com.swak.utils.JsonMapper;
import com.swak.utils.StringUtils;
import com.swak.validator.errors.BindErrors;

import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

/**
 * JSON 返回的基本结构
 *
 * @author: lifeng
 * @date: 2020/3/29 11:20
 */
@Getter
@Setter
@Accessors(chain = true)
@ApiDoc(value = "统一的返回", example = "")
public class Result<T> implements Serializable {

	private static final long serialVersionUID = 1L;

	/**
	 * 响应码
	 */
	@ApiDoc("响应码：具体参考：ErrorCode")
	private int code = ErrorCode.OPERATE_SECCESS.getCode();

	/**
	 * 响应消息
	 */
	@ApiDoc("响应消息：操作成功/操作失败：显示操作失败消息")
	private String msg = "操作成功";

	/**
	 * 响应结果
	 */
	@ApiDoc("响应结果：true/false")
	private boolean success;

	/**
	 * 返回的结果
	 */
	@ApiDoc("响应结果：具体的响应数据")
	private T obj = null;

	/**
	 * 如果验证异常，则通过此字段返回
	 */
	@ApiDoc("响应结果：参数校验异常")
	private BindErrors bindError;

	/**
	 * 是否响应成功
	 */
	public boolean isSuccess() {
		return ErrorCode.OPERATE_SECCESS.getCode() == this.code;
	}

	/**
	 * 得到json格式的数据
	 *
	 * @return json 格式
	 */
	public String toJson() {
		return JsonMapper.toJson(this);
	}

	/**
	 * 默认的成功消息
	 *
	 * @return Result
	 */
	public static <T> Result<T> success() {
		return new Result<T>();
	}

	/**
	 * 返回对象
	 *
	 * @param o 数据
	 * @return Result
	 */
	public static <T> Result<T> success(T o) {
		Result<T> result = Result.success();
		result.setObj(o);
		return result;
	}

	/**
	 * 指定错误消息、错误对象
	 *
	 * @param msg 错误消息
	 * @return Result
	 */
	public static <T> Result<T> error(String msg) {
		Result<T> result = new Result<T>();
		result.setCode(ErrorCode.OPERATE_FAILURE.getCode());
		result.setMsg(msg);
		return result;
	}

	/**
	 * 指定错误消息、错误对象
	 *
	 * @param msg 错误消息
	 * @param o   错误的对象
	 * @return Result
	 */
	public static <T> Result<T> error(T o) {
		Result<T> result = new Result<T>();
		result.setCode(ErrorCode.OPERATE_FAILURE.getCode());
		result.setMsg("操作失败");
		result.setObj(o);
		return result;
	}

	/**
	 * 指定错误消息、错误对象
	 *
	 * @param msg 错误消息
	 * @param o   错误的对象
	 * @return Result
	 */
	public static <T> Result<T> error(String msg, T o) {
		Result<T> result = new Result<T>();
		result.setCode(ErrorCode.OPERATE_FAILURE.getCode());
		result.setMsg(msg);
		result.setObj(o);
		return result;
	}

	/**
	 * 格式化输出
	 *
	 * @param template 错误的模板
	 * @param msg      消息
	 * @return Result
	 */
	public static <T> Result<T> error(String template, Object... msg) {
		return error(StringUtils.format(template, msg));
	}

	/**
	 * 通过 ErrorCode 返回错误信息
	 *
	 * @param code 错误码
	 * @return Result
	 */
	public static <T> Result<T> error(ErrorCode code) {
		Result<T> result = new Result<T>();
		result.setCode(code.getCode());
		result.setMsg(code.getMsg());
		return result;
	}

	/**
	 * 通过 ErrorCode 返回错误信息
	 *
	 * @param code 错误码
	 * @return Result
	 */
	public static <T> Result<T> error(BindErrors errors) {
		Result<T> result = new Result<T>();
		result.setCode(ErrorCode.BIND_ERRORS.getCode());
		result.setMsg(ErrorCode.BIND_ERRORS.getMsg());
		result.setBindError(errors);
		return result;
	}

	/**
	 * 返回错误信息
	 * 
	 * @param msg
	 * @return
	 */
	public static <T> CompletionStage<Result<T>> errorCompletedFuture(ErrorCode error) {
		return CompletableFuture.completedFuture(Result.error(error));
	}

	/**
	 * 返回错误信息
	 * 
	 * @param msg
	 * @return
	 */
	public static <T> CompletionStage<Result<T>> errorCompletedFuture(String msg) {
		return CompletableFuture.completedFuture(Result.error(msg));
	}

	/**
	 * 返回错误信息
	 * 
	 * @param msg
	 * @return
	 */
	public static <T> CompletionStage<Result<T>> errorCompletedFuture(BindErrors errors) {
		return CompletableFuture.completedFuture(Result.error(errors));
	}

	/**
	 * 返回错误信息
	 * 
	 * @param msg
	 * @return
	 */
	public static <T> CompletionStage<Result<T>> errorCompletedFuture(T msg) {
		return CompletableFuture.completedFuture(Result.error(msg));
	}

	/**
	 * 返回成功信息
	 * 
	 * @param msg
	 * @return
	 */
	public static <T> CompletionStage<Result<T>> successCompletedFuture() {
		return CompletableFuture.completedFuture(Result.success());
	}

	/**
	 * 函数式编程，接收异步结果 ： thenApply(Result.successFunction());
	 * 
	 * @return
	 */
	public static <T> Function<T, Result<T>> successFunction() {
		return (t) -> Result.success(t);
	}
}